#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

#define  LOCAL_PORT      5350
#define  MCAST_ADDR      "224.0.0.251"
#define  MCAST_INTERVAL    5
#define  LOCAL_ADDR   "192.168.42.201"

void bind_multicast(int sock)
{
    int err = -1;

    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR);
    mreq.imr_interface.s_addr = inet_addr(LOCAL_ADDR);
    err = setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
    if(err < 0){
        printf("%s setsockopt():IP ADD MEMBURSHIP\n",strerror(errno));
        exit(1);
    } else {
        printf("setsockopt() IP ADD MEMBURSHIP sucessful\n");
    }
}

void server(int sock){
    //1、建立接收缓存字节数组
    char recvbuf[1024] = {0};
    //2、定义socket
    struct sockaddr_in peeraddr;
    socklen_t peerlen;
    int n;
    while(1){
        //
        peerlen = sizeof(peeraddr);
        //3、清空接收缓存数组
        memset(recvbuf, 0, sizeof(recvbuf));
        //4、开始接收数据
        n = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&peeraddr, &peerlen);

        //5、判断是否接收完整数据
        if(n == -1){
                perror("recvfrom"); 
                exit(EXIT_FAILURE); 
        }else if(n > 0){
            printf("recvbuf=%s\n", recvbuf);
            //6、成功接收数据，将缓存数据写入到标准输出，打印到控制台
            fputs(recvbuf, stdout);
            //7、想客户端回送接收到的数据(回显客户端输入的数据)
            sendto(sock, recvbuf, n, 0, (struct sockaddr *)&peeraddr, peerlen);
        }
    }
    //关闭socket
    close(sock);
}
 
int main(void){
        int sock;
        //创建服务器socket
        if((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0){
            perror("socket error");
            exit(EXIT_FAILURE);
        }
        //设置服务器socket参数
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        //设置socket的协议、端口以及地址
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(LOCAL_PORT);
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        //将socket绑定地址
        if(bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
            perror("bind error");
            exit(EXIT_FAILURE);
        }

        //bind_multicast(sock);
        server(sock);
        return 0;
}